#pragma once
#include <streambuf>

namespace Pdf
{
    /*******************************************************************
    HANDLER CONTRACT:

    struct Handler : public Scanner<Handler>
    {
        void    onCharacter(char c);
        void    onEnterWhiteSpace();
        void    onLeaveWhiteSpace();
        void    onEnterEOL();
        void    onLeaveEOL();
        void    onEnterComment();
        void    onLeaveComment();
        void    onEnterString();
        void    onLeaveString();
        void    onEnterDictionary();
        void    onLeaveDictionary();
        void    onEnterName();
        void    onLeaveName();
        void    onEnterArray();
        void    onLeaveArray();
        void    onEnterNames();
        void    onLeaveNames();
        void    onEnterToken();
        void    onLeaveToken();
    };

    *******************************************************************/

    template <typename Handler>
    struct Scanner
    {
        std::streambuf::int_type    scanNext(std::streambuf::int_type c, std::streambuf *s);
        std::streambuf::int_type    scanWhiteSpace(std::streambuf::int_type c, std::streambuf *s) throw();
        std::streambuf::int_type    scanEOL(std::streambuf::int_type c, std::streambuf *s) throw();
        std::streambuf::int_type    scanEOL2(std::streambuf::int_type c, std::streambuf *s) throw();
        std::streambuf::int_type    scanLine(std::streambuf::int_type c, std::streambuf *s) throw();
        std::streambuf::int_type    scanLexString(std::streambuf::int_type c, std::streambuf *s) throw();
        std::streambuf::int_type    scanLexStringEsc(std::streambuf::int_type c, std::streambuf *s);
        std::streambuf::int_type    scanLexStringOct(std::streambuf::int_type c, std::streambuf *s) throw();
        std::streambuf::int_type    scanLexStringEOL(std::streambuf::int_type c, std::streambuf *s) throw();
        std::streambuf::int_type    scanLexStringEOL2(std::streambuf::int_type c, std::streambuf *s) throw();
        std::streambuf::int_type    scanDictionaryBeg(std::streambuf::int_type c, std::streambuf *s) throw();
        std::streambuf::int_type    scanDictionaryEnd(std::streambuf::int_type c, std::streambuf *s);
        std::streambuf::int_type    scanHexString(std::streambuf::int_type c, std::streambuf *s);
        std::streambuf::int_type    scanToken(std::streambuf::int_type c, std::streambuf *s) throw();
        std::streambuf::int_type    scanName(std::streambuf::int_type c, std::streambuf *s) throw();
        std::streambuf::int_type    scanNameEsc(std::streambuf::int_type c, std::streambuf *s);
    };
}

#include "scanner.inl"